<?php
//网站主页
class Index extends CI_Controller
{
    private $GetwayWorker;
    private $page_size = 20;
    private $real_ip;
    private $en_to_uid;

    public function __construct()
    {
        parent::__construct();

        header("Access-Control-Allow-Origin: https://www.taoerhuo.top");//允许本站跨域
        header('Content-type:text/html;charset=utf-8');
        header("access-control-allow-headers: Origin, X-Requested-With, Content-Type, Accept,WG-App-Version, WG-Device-Id, WG-Network-Type, WG-Vendor, WG-OS-Type, WG-OS-Version, WG-Device-Model, WG-CPU, WG-Sid, WG-App-Id, WG-Token,Chat");

        ini_set('memory_limit','300M');

        $this->load->model('chat_model','chat_model');

        $this->load->helper("url");

        require_once(APPPATH . 'libraries/GetwayWorker.php');

        $this->GetwayWorker = new GetwayWorker();

        $this->real_ip = plum_get_realIP();
        //ip黑名单
        // $bla = ip_black($this->real_ip);

        // if (!$bla)
        // {
        //     displayJson(400,'别在这霍霍了，你妈在火葬场粘锅了！');
        // }

        //id解密
        if (isset($_POST['user_id']))
        {
            $old = $_POST['user_id'];
            $_POST['user_id'] = decode_uid($_POST['user_id']);

            if (!$_POST['user_id'])
            {
                log_message('error','异常用户-user_id-'.$old);
                
                displayJson(400,'异常用户！');
            }
        }

        if (isset($_POST['to_uid']))
        {
            $this->en_to_uid = $_POST['to_uid'];

            $_POST['to_uid'] = decode_uid($_POST['to_uid']);

            if (!is_numeric($_POST['to_uid']))
            {
                log_message('error','异常用户-to_uid-'.$this->en_to_uid);
                displayJson(400,'异常用户！');
            }
        }

        if (isset($_POST['uid']))
        {
            $old = $_POST['uid'];
            $_POST['uid'] = decode_uid($_POST['uid']);

            if (!$_POST['uid'])
            {
                log_message('error','异常用户-uid-'.$old);
                displayJson(400,'异常用户！');
            }
        }
    }

    //主页
    public function index()
    {
        //获取当前在线列表
        $lines = $this->GetwayWorker->getUidListByGroup('public');

        $list  = [];
        if (!empty($lines))
        {
            $this->load->database();
            $this->db->select('A.encode_id as id,A.client_id,A.nick_name,A.real_ip,B.url');
            $this->db->from('user_log as A');
            $this->db->join('avatar AS B', 'A.avatar_id = B.id', 'LEFT');
            $this->db->where_in('A.encode_id',$lines);
            $query  = $this->db->get();
            $list   = $query->result_array();

            $this->db->close();

            $now_ip = $this->real_ip;

            //去掉自己
            foreach ($list as $k => &$v)
            {
                if ($v['real_ip'] == $now_ip)
                {
                    unset($list[$k]);
                }

                $v['url'] = base_url().$v['url'];
            }
        }

        $users['list'] = $list;

        $this->load->view("chat",$users);
    }

    public function captcha()
    {
        $this->load->library('Captcha');

        $Captcha = new Captcha();

        $redis = initRedis();

        $code  = random(_CAPTCHA_);

        $Captcha->getCode($code,60,20,$redis,$this->real_ip);
    }

    //生成并绑定用户：一个ip一个用户
    public function bindUser()
    {
        //displayJson(400,'？');
        if (empty($_POST))
        {
            displayJson(400,'滚球');
        }

        $this->check_header();
        $this->load->database();

        $real_ip  = $_POST['real_ip'];

        $ip_again = $this->real_ip;

        //先查找
        $this->db->select('encode_id as id,nick_name');
        $this->db->where('real_ip',$real_ip);
        $query = $this->db->get('user_log');
        $check = $query->row();

        //获取随机头像id
        $this->db->select('id,url');
        $this->db->from('avatar');
        $this->db->order_by('RAND()');
        $this->db->limit(1);
        $query  = $this->db->get();
        $avatar = $query->result_array();

        if (empty($check))
        {
            if (!isset($_POST['nick']) || empty($_POST['nick']) || !isset($_POST['code']) || empty($_POST['code']))
            {
                displayJson(400,'必填项不能为空');
            }

            $code = trim($_POST['code']);

            $redis = initRedis();

            $real_code = $redis->get('mycode_'.$ip_again);
            
            log_message('error','bindUser-'.json_encode($_POST,JSON_UNESCAPED_UNICODE).'-real-'.$real_code);

            if (strtolower($code) !== $real_code)
            {
                //频繁检测--5秒超过10次屏蔽1分钟
                $frequently = $this->checkFrequently($real_ip);

                if (!$frequently)
                {
                    displayJson(400,'操作过于频繁，你被禁言5分钟');
                }

                displayJson(400,'验证码错误');
            }

            //删除验证码redis
            $redis->del('mycode_'.$ip_again);

            $address = plum_ip_get_address($ip_again);

            //新增
            $this->db->trans_start();

            $data = [
                'nick_name'		=> mb_substr($_POST['nick'],0,10,'utf-8'),
                'avatar_id'		=> $avatar[0]['id'],
                'client_id'		=> $_POST['client_id'],
                'real_ip'       => $real_ip,
                'province'	    => $address['province'],
                'city'			=> $address['city'],
            ];
            $this->db->set('start_time', 'NOW()', FALSE);
            $this->db->insert('user_log', $data);

            $uid = $this->db->insert_id();

            $en_uid = encode_uid($uid);

            $this->db->set('encode_id', $en_uid);
            $this->db->where('id', $uid);
            $this->db->update('user_log');

            $this->db->trans_complete();

            if ($this->db->trans_status() === FALSE) {
                log_message('error','用户添加失败'.$this->db->_error_message());
                $this->db->close();
                displayJson(400,'服务器链接失败,请稍后重试');
            }

            $nick = $data['nick_name'];

            $uid  = $en_uid;
        } else {
            //更新
            $this->db->trans_start();

            if ($real_ip != $ip_again)
            {
                $address = plum_ip_get_address($ip_again);

                $this->db->set('real_ip', $ip_again);
                $this->db->set('province', $address['province']);
                $this->db->set('city', $address['city']);
            }
            $this->db->set('client_id', $_POST['client_id']);
            $this->db->set('avatar_id', $avatar[0]['id']);
            $this->db->where('encode_id', $check->id);
            $this->db->update('user_log');

            if ($this->db->trans_status() === FALSE) {
                log_message('error','用户更新失败'.$this->db->_error_message().'-id-'.$check->id);
                $this->db->close();
                displayJson(400,'服务器链接失败,请稍后重试');
            }

            $uid  = $check->id;

            $nick = $check->nick_name;
        }

        //获取近7天聊天记录
        $time = date ('Y-m-d', strtotime("-7 day",time()));
        
        //$time = date ('Y-m-d');

        $_POST['page'] = isset($_POST['page']) ? $_POST['page'] : 0;

        $this->db->select('B.encode_id as uid,,A.content,A.create_time,B.nick_name,B.province,B.city,C.url');
        $this->db->from('content as A');
        $this->db->join('user_log AS B', 'A.uid = B.id', 'LEFT');
        $this->db->join('avatar AS C', 'B.avatar_id = C.id', 'LEFT');
        //$this->db->where('A.create_time >=',$time);
        $this->db->where('A.to_uid',0);
        $this->db->order_by('A.id','DESC');

        $offset = $_POST['page'] * $this->page_size;
        $this->db->limit($this->page_size, $offset);

        $query  = $this->db->get();
        $list   = $query->result_array();

        $this->db->close();

        //绑定用户 加入组
        $this->GetwayWorker->bindUid($uid,$_POST['client_id'],'public');

        //处理聊天记录
        if (!empty($list))
        {
            foreach ($list as $key => &$val)
            {
                $val['url']  = base_url().$val['url'];
                $ci          = !empty($val['city']) ? $val['city'] : $val['province'];
                $val['city'] = str_replace('市', '', $ci);

                if ($val['create_time'] >= date('Y-m-d',time()))
                {
                    $val['create_time'] = date('H:i',strtotime($val['create_time']));
                } else {
                    $val['create_time'] = date('m-d H:i',strtotime($val['create_time']));
                }
            }
        }

        // 向所有人发送(去除当前用户)，表示有新用户连接
        $all = [
            'type'      => 'connect',
            'msg'       => '有新的用户连接',
            'id'        => $uid,
            'nick'      => $nick,
            'avatar'    => base_url().$avatar[0]['url'],
            'ip'        => $real_ip,
        ];
        $this->GetwayWorker->sendToAll(json_encode($all,JSON_UNESCAPED_UNICODE),[$_POST['client_id']]);

        $my = [
            'avatar'  => base_url().$avatar[0]['url'],
            'nick'    => $nick,
            'user_id' => $uid,
            'list'    => $list,
        ];
        displayJson(200,'success',$my);
    }

    //记录用户聊天记录
    public function chatRecord()
    {
        $this->check_header();

        if (
            isset($_POST['content']) && !empty($_POST['content']) &&
            isset($_POST['user_id']) && !empty($_POST['user_id']) &&
            isset($_POST['client_id']) && !empty($_POST['client_id']) &&
            isset($_POST['to_uid'])
        ) {
            $_POST['content'] = trim($_POST['content']);

            $_POST['content'] = cleanhtml($_POST['content']);

            $em = str_replace('&nbsp;','', $_POST['content']);
          
            if (empty(trim($em)))
            {
                displayJson(400,'不能发送空白消息');
            }

            if ($_POST['user_id'] == $_POST['to_uid'])
            {
                displayJson(400,'你发信息给自己干嘛？');
            }

            if (strlen(strip_tags($_POST['content'])) > 500)
            {
                displayJson(400,'内容过长');
            }

            //特殊字符检测
            $te = no_mom_str($_POST['content']);

            if (!empty($te))
            {
                displayJson(400,'别在这霍霍了，你妈在火葬场粘锅了！');
            }

            //频繁检测--5秒超过10次屏蔽1分钟
            $frequently = $this->checkFrequently($this->real_ip);

            if (!$frequently)
            {
                displayJson(400,'操作过于频繁，你被禁言5分钟');
            }

            $this->load->database();

            $this->db->select('A.encode_id as id,A.nick_name,A.province,A.city,B.url');
            $this->db->from('user_log as A');
            $this->db->join('avatar AS B', 'B.id = A.avatar_id', 'LEFT');
            $this->db->where('A.id',$_POST['user_id']);
            $query = $this->db->get();
            $user  = $query->row();

            if (empty($user))
            {
                displayJson(400,'别在这霍霍了，你妈在火葬场粘锅了！');
            }

            $this->db->trans_start();

            $data = [
                'uid'		  => $_POST['user_id'],
                'to_uid'      => $_POST['to_uid'],
                'content'     => $_POST['content'],
                'create_time' => date('Y-m-d H:i:s',time())
            ];

            $this->db->insert('content', $data);

            $this->db->trans_complete();

            if ($this->db->trans_status() === FALSE) {
                log_message('error','记录用户聊天失败'.$this->db->_error_message().'-post-'.json_encode($_POST));
                $this->db->close();
                displayJson(400,'服务器繁忙,请稍后重试');
            }

            $this->db->close();

            $ci   = !empty($user->city) ? $user->city : $user->province;
            $city = str_replace('市', '', $ci);
            //向大厅组发送消息--不给当前用户发
            $con = array(
                'type'      => 'text',
                'msg'       => $data['content'],
                'client_id' => $_POST['client_id'],
                'nick'      => $user->nick_name,
                'avatar'    => base_url().$user->url,
                'time'      => date('H:i',time()),
                'from_uid'  => $user->id,
                'to_uid'    => $this->en_to_uid,
                'city'      => $city,
            );

            if ($_POST['to_uid'] > 0)
            {
                //向单个用户
                $this->GetwayWorker->sendMessageToUid($this->en_to_uid,json_encode($con,JSON_UNESCAPED_UNICODE));
            } else {
                //向大厅
                $this->GetwayWorker->sendToGroup('public',json_encode($con,JSON_UNESCAPED_UNICODE),[$_POST['client_id']]);
            }

            $ret = [
                'content' => $data['content'],
                'time'    => date('H:i',time()),
                'avatar'  => base_url().$user->url,
                'nick'    => $user->nick_name,
            ];

            displayJson(200,'发送成功',$ret);
        } else {
            displayJson(400,'数据异常，请稍后重试');
        }
    }

    //发送图片
    public function sendImage()
    {
        $this->check_header();
        if (
            !isset($_POST['client_id']) || empty($_POST['client_id']) ||
            !isset($_POST['uid']) || empty($_POST['uid']) ||
            !isset($_POST['to_uid'])
        )
        {
            displayJson(400,'发送失败，请刷新后重试');
        }

        if (!isset($_FILES['image']) || empty($_FILES['image']))
        {
            displayJson(401,'请选择图片/视频');
        }

        //频繁检测--5秒超过10次屏蔽1分钟
        $frequently = $this->checkFrequently($this->real_ip);

        if (!$frequently)
        {
            displayJson(400,'操作过于频繁，你被禁言5分钟');
        }

        $this->load->database();
        $this->db->select('encode_id');
        $this->db->from('user_log');
        $this->db->where('id',$_POST['uid']);
        $query = $this->db->get();
        $user  = $query->row();
        $this->db->close();

        if (empty($user))
        {
            displayJson(400,'别在这霍霍了，你妈在火葬场粘锅了！');
        }

        $res = $this->chat_model->sendImage();

        if ($res['ec'] == 400)
        {
            displayJson(400,$res['em']);
        }

        $con = array(
            'type'      => 'text',
            'msg'       => $res['data']['content'],
            'client_id' => $_POST['client_id'],
            'nick'      => $res['data']['nick'],
            'avatar'    => $res['data']['avatar'],
            'time'      => $res['data']['time'],
            'from_uid'  => $user->encode_id,
            'to_uid'    => $this->en_to_uid,
            'city'      => $res['data']['city'],
        );

        //消息推送
        if ($_POST['to_uid'] > 0)
        {
            //向单个用户
            $this->GetwayWorker->sendMessageToUid($this->en_to_uid,json_encode($con,JSON_UNESCAPED_UNICODE));
        } else {
            //向大厅
            $this->GetwayWorker->sendToGroup('public',json_encode($con,JSON_UNESCAPED_UNICODE),[$_POST['client_id']]);
        }

        displayJson(200,'发送成功',$res['data']);
    }

    //获取聊天记录-分页
    public function getPageChatRecord()
    {
        if (!isset($_POST['page']) || !is_numeric($_POST['page']))
        {
            displayJson(400,'分页参数丢失');
        }

        $this->load->database();

        //获取近7天聊天记录
        $time = date ('Y-m-d', strtotime("-7 day",time()));
        //$time = date ('Y-m-d');
     
        $this->db->select('B.encode_id as uid,A.content,A.create_time,B.nick_name,B.province,B.city,C.url');
        $this->db->from('content as A');
        $this->db->join('user_log AS B', 'A.uid = B.id', 'LEFT');
        $this->db->join('avatar AS C', 'B.avatar_id = C.id', 'LEFT');
        //$this->db->where('A.create_time >=',$time);

        if ((int)$_POST['to_uid'] == 0)
        {
            $this->db->where('A.to_uid',$_POST['to_uid']);
        } else {
            //点击的是私人
            $this->db->where_in('A.uid',[$_POST['user_id'],$_POST['to_uid']]);
            $this->db->where_in('A.to_uid',[$_POST['user_id'],$_POST['to_uid']]);
        }

        $this->db->order_by('A.id','DESC');

        $offset = $_POST['page'] * $this->page_size;
        $this->db->limit($this->page_size, $offset);

        $query  = $this->db->get();

        $list   = $query->result_array();

        //处理聊天记录
        if (!empty($list))
        {
            foreach ($list as $key => &$val)
            {
                $val['url']  = base_url().$val['url'];
                $ci          = !empty($val['city']) ? $val['city'] : $val['province'];
                $val['city'] = str_replace('市', '', $ci);

                if ($val['create_time'] >= date('Y-m-d',time()))
                {
                    $val['create_time'] = date('H:i',strtotime($val['create_time']));
                } else {
                    $val['create_time'] = date('m-d H:i',strtotime($val['create_time']));
                }
            }
        }

        $this->db->close();

        $data['list'] = $list;

        $msg = empty($list) ? '已加载完毕' : '加载成功';

        displayJson(200,$msg,$data);
    }

    //投稿头像
    public function uploadAvatar()
    {
        $this->check_header();
        if (!isset($_POST['uid']) || empty($_POST['uid']) || !isset($_FILES['image']) || empty($_FILES['image']))
        {
            displayJson(400,'上传失败，请刷新后重试');
        }

        //频繁检测--5秒超过10次屏蔽1分钟
        $frequently = $this->checkFrequently($this->real_ip);

        if (!$frequently)
        {
            displayJson(400,'操作过于频繁，你被禁言5分钟');
        }

        $this->chat_model->uploadAvatar();
    }

    //Redis频繁检测
    public function checkFrequently($ip)
    {
        $redis = initRedis();

        $key_uid    = 'chat_num_uid_'.$ip;
        $key_time   = 'chat_time_uid_'.$ip;

        $start = $redis->get($key_time);

        //先检测是否有禁言时间
        if (!empty($start))
        {
            return false;
        }

        $check = $redis->get($key_uid);

        if (!empty($check))
        {
            if ($check >= _Chat_Num_)
            {
                $redis->set($key_time,1,300); //禁言5分钟
                return false;
            } else {
                $redis->incr($key_uid); //自加1

                return true;
            }
        } else {
            $redis->set($key_uid,1,5);

            return true;
        }
    }

    //根据客户端id获取用户
    public function getUserByClient()
    {
        if (!isset($_POST['real_ip']) || empty($_POST['real_ip']))
        {
            displayJson(400,'参数丢失');
        }

        $this->load->database();

        $this->db->select('encode_id');
        $this->db->from('user_log');
        $this->db->where('real_ip',$_POST['real_ip']);
        $query = $this->db->get();
        $user  = $query->row();

        $this->db->close();

        if (empty($user))
        {
            displayJson(400,'用户未找到');
        }

        $data['id'] = $user->encode_id;
        displayJson(200,'success',$data);
    }

    //改昵称
    public function editNick()
    {
        $this->check_header();
        if (!isset($_POST['nick']) || empty($_POST['nick']))
        {
            displayJson(400,'昵称不能为空');
        }

        if (
            !isset($_POST['user_id']) || empty($_POST['user_id']) ||
            !isset($_POST['client_id']) || empty($_POST['client_id'])
        )
        {
            displayJson(400,'请刷新后重试');
        }

        //频繁检测--5秒超过10次屏蔽1分钟
        $frequently = $this->checkFrequently($this->real_ip);

        if (!$frequently)
        {
            displayJson(400,'操作过于频繁，你被禁言5分钟');
        }

        $_POST['nick'] = mb_substr($_POST['nick'],0,10,'utf-8');

        $_POST['nick'] = htmlspecialchars($_POST['nick']);

        $this->load->database();

        $this->db->select('encode_id');
        $this->db->from('user_log');
        $this->db->where('id',$_POST['user_id']);
        $query = $this->db->get();
        $user  = $query->row();

        if (empty($user))
        {
            $this->db->close();
            displayJson(400,'异常用户！');
        }

        $this->db->trans_start();

        $this->db->set('nick_name', $_POST['nick']);
        $this->db->where('id', $_POST['user_id']);
        $this->db->update('user_log');

        $this->db->trans_complete();

        if ($this->db->trans_status() === FALSE) {
            $this->db->close();
            displayJson(400,'服务器链接失败,请稍后重试');
        }

        $this->db->close();

        // 向所有人发送(去除当前用户)
        $all = [
            'type'      => 'change',
            'msg'       => '用户更改昵称',
            'id'        => $user->encode_id,
            'nick'      => $_POST['nick'],
        ];
        $this->GetwayWorker->sendToAll(json_encode($all,JSON_UNESCAPED_UNICODE),[$_POST['client_id']]);

        displayJson(200,'修改成功');
    }


    //检测头部header
    public function check_header()
    {
        $headers = em_getallheaders();

        if (!isset($headers['Chat']) || empty($headers['Chat']))
        {
            displayJson(400,'非法请求');
        }

        //判断请求方式
        if (!IS_POST)
        {
            displayJson(400,'ERR：非法请求');
        }

        $redis = initRedis();
        
        //获取集合
        //$test = $redis->sMembers('discard_token');
        

        //验证token有没有用过
        $check_dis = $redis->sIsMember('discard_token',$headers['Chat']);

        if ($check_dis)
        {
            displayJson(400,'请求异常！');
        }

        //解密
        $hex_encrypt_data = trim($headers['Chat']); //十六进制数据
        $encrypt_data     = pack("H*", $hex_encrypt_data);//对十六进制数据进行转换

        openssl_private_decrypt($encrypt_data, $decrypt_data, _PRIVATE_);

        if ($decrypt_data != _HEADER_PASS_)
        {
            displayJson(400,'请求失败！');
        }

        //将此token加入废弃集合
        $redis->sAdd('discard_token',$headers['Chat']);
    }


}
